<script>

  const flatArr = [
    { id: '0011', parentId: '001', name: '节点1-1' },
    { id: '001', name: '节点1' },
    { id: '00111', parentId: '0011', name: '节点1-1-1' },
    { id: '002', name: '节点2' },
  ]

  function toTree(arr) {
    const result = [];
    const map = {};

    flatArr.forEach(item => {

      map[item.id] = map[item.id] ? {
        ...map[item.id],
        ...item
      } : {...item};

      const treeItem = map[item.id];

      if(item.parentId) {
        if(!map[item.parentId]) {
          map[item.parentId] = {};
        }

        const parent = map[item.parentId];

        if(!parent.children) {
          parent.children = [];
        }
        parent.children.push(treeItem);
      } else {
        result.push(treeItem);
      }
    })

    console.log(map);
    return result;
  }

  console.log(toTree(flatArr));

  function toTree2(arr, rootId) {
    const map = {},
          result = [];
    arr.forEach(item => {
      const { id, parentId } = item;

      // 针对顺序错乱的情况的兼容（子在父前）
      map[id] = !map[id] ? {...item} : {
        ...item,
        ...map[id]
      }

      const treeItem = map[id];

      if(!item.parentId) {
        result.push(treeItem);
      }  else {
        if(!map[parentId]) {
          map[parentId] = {}
        }
        if(!map[parentId].children) {
          map[parentId].children = [];
        }
        // 找到父级节点的地址，往父级的children添加当前节点
        map[parentId].children.push(treeItem);
      }
    })
    return result;
  }
  console.log(toTree2(flatArr));

  function toTree3(arr) {
    return arr
      // 浅拷贝，避免影响源数组
      .map(item => ({...item}))
      .filter(item => {
        // 过滤出儿子，赋值到children
        item.children = arr.filter(item1 => item.id === item1.parentId)
        // 过滤出顶层节点(无parentId表示为顶层)
        return !item.parentId
      })
  }


  console.log(toTree3(flatArr));

  console.log(flatArr);
</script>
